package structpackage

import (
	"fmt"
	"reflect"
	"strconv"
)

type test1Struct struct {
	a int
	b float32
	c string
}

type node struct {
	value int
	next  *node
}

func test1() {
	s1 := new(test1Struct)
	s1.a = 10
	s1.b = 10.0
	s1.c = "hello go"
	fmt.Println(s1)

	var s2 test1Struct
	s2.a = 20
	s2.b = 20.0
	s2.c = "hello goo"
	fmt.Println(s2)

	s3 := test1Struct{10, 20.0, "hello go"}
	fmt.Println(s3)

	s4 := test1Struct{a: 20, c: "hello oo"}
	fmt.Println(s4)

	s5 := &test1Struct{a: 10, b: 20}
	fmt.Println(s5)
}

type test2S1 struct {
	f float32
}

type test2S2 struct {
	f float32
}

func test2() {
	a := test2S1{10.0}
	b := test2S2{11.1}
	fmt.Println(a, b)

	var c test2S2
	//c = a 无法将 'a' (类型 test2S1) 用作类型 test2S2
	c = test2S2(a)
	fmt.Println(c)
}

type test3File struct {
	fd   int    // 文件描述符
	name string // 文件名
}

func test3NewFile(fd int, name string) *test3File {
	if fd < 0 {
		return nil
	}
	return &test3File{fd, name}
}

func Test3NewFile(fd int, name string) *test3File {
	if fd < 0 {
		return nil
	}
	return &test3File{fd, name}
}

func test3() {
	f := test3NewFile(10, "./hello.txt")
	fmt.Println(f)
}

type test4Struct struct {
	str    string "this is string"
	number int    "this is number"
}

func test4RefTag(t4s test4Struct, idx int) {
	structType := reflect.TypeOf(t4s)
	ixFiled := structType.Field(idx)
	fmt.Println(ixFiled.Tag)
}

func test4() {
	tt := test4Struct{
		str:    "hello go",
		number: 0,
	}
	for i := 0; i < 2; i++ {
		test4RefTag(tt, i)
	}
}

type inner struct {
	inner1 int
	inner2 string
}

type outer struct {
	flag   bool
	number int
	int
	inner
}

func test5() {
	//o1 := new(outer)
	var o1 outer
	o1.flag = false
	o1.number = 10
	o1.int = 20
	o1.inner1 = 10
	o1.inner2 = "hello go"
	fmt.Println(o1)
}

type test6S struct {
	thing int
}

func (ts *test6S) change1() {
	ts.thing = 20
}

func (ts test6S) change2() {
	ts.thing = 20
}

func test6() {
	ts1 := test6S{thing: 10}
	ts2 := test6S{thing: 10}

	ts1.change1()
	fmt.Println(ts1)

	ts2.change2()
	fmt.Println(ts2)
}

type Test7S struct {
	firstname string
	lastname  string
}

func (ts *Test7S) GetFirstname() string {
	return ts.firstname
}

func (ts *Test7S) GetLastname() string {
	return ts.lastname
}

func (ts *Test7S) SetFirstname(fn string) {
	ts.firstname = fn
}

func (ts *Test7S) SetLastname(ln string) {
	ts.lastname = ln
}

type Camera struct{}

func (c *Camera) TakeAPicture() string {
	return "Click"
}

type Phone struct{}

func (p *Phone) Call() string {
	return "Ring Ring"
}

type CameraPhone struct {
	Camera
	Phone
}

func test7() {
	cp := new(CameraPhone)
	fmt.Println("Our new CameraPhone exhibits multiple behaviors...")
	fmt.Println("It exhibits behavior of a Camera: ", cp.TakeAPicture())
	fmt.Println("It works like a Phone too: ", cp.Call())
}

type test8S struct {
	a int
	b int
}

func (ts test8S) String() string {
	return "my format hhh: " + strconv.Itoa(ts.a) + " and " + strconv.Itoa(ts.b)
}

func test8() {
	ts1 := test8S{10, 20}
	ts2 := &test8S{10, 20}
	fmt.Println(ts1)
	fmt.Println(ts2)
}

func Test() {
	test8()
}
